#ifndef _METHODDEFINITION_
#define _METHODDEFINITION_

#include "TreeNode.h"
#include "Variable.h"
#include "Statement.h"
#include "FunctionDefinition.h"
#include "VarDeclaration.h"
#include <string>
#include <vector>

using namespace std;

class ClassDefinition; // dopredna deklarace kvuli fieldu fClassDef

class MethodDefinition: public TreeNode
{
public:
    MethodDefinition(string iMethodName, vector<Variable*> iInputVariables, TreeNode* iBody);
    virtual ~MethodDefinition();
    virtual void Accept(GeneralVisitor*);

    void CheckFunctionCalls(set<FunctionDefinition*>& iAllFunctions, string iParentName);
    void CheckClassConstructions(set<ClassDefinition*>& iAllClasses, string iParentName);
    void CheckVariables(set<string>& iClassFieldNames, string iParentName);
    void CheckExpressionTypes(set<string>& iClassFieldNames, string iParentName);

    string              GetName()                           { return this->fMethodName; }
    unsigned int        GetParamCount()                     { return fInputVariables.size(); }
    unsigned int        GetLocalsCount()                    { return fLocalVars.size() - fInputVariables.size(); }
    ClassDefinition*    GetClassDef()                       { return this->fClassDef; }
    void                SetClassDef(ClassDefinition* iDef)  { this->fClassDef = iDef; }

    // Vrati ukazatel na ReturnStatement obsazeny v fBody, nebo 0, pokud tam zadny takovy neni.
    ReturnStatement*    GetReturnStatement();

    TreeNode* GetBody() { return fBody; }

    vector<string> GetInputVarNames();
    vector<string> GetLocalVarNames();

    void SetBytecodeOffset(unsigned int iBytecodeOffset)    { fBytecodeOffset = iBytecodeOffset; }
    unsigned int GetBytecodeOffset()                        { return fBytecodeOffset; }

    bool IsConstructor()        { return fIsConstructor; }
    void SetConstructorFlag()   { fIsConstructor = true; }

private:
    string fMethodName;
    vector<Variable*> fInputVariables;
    TreeNode* fBody;
    ClassDefinition* fClassDef; // toto je pointer na tridu, ktera metodu definuje
    set<string> fLocalVars;
    unsigned int fBytecodeOffset;
    bool fIsConstructor;
};

#endif
